/*
 * @(#)DaapListener.java
 * 
 * Copyright(C) 2004 Yujin Kim
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.netexplode.jtunes.protocol.jmdns;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cdavies.itunes.Database;
import org.cdavies.itunes.ItunesConnection;
import org.cdavies.itunes.ItunesConnectionFactory;
import org.cdavies.itunes.ItunesHost;
import org.cdavies.itunes.request.NoServerPermissionException;

import com.netexplode.jtunes.Constants;
import com.netexplode.jtunes.client.player.jTunes;
import com.netexplode.jtunes.model.media.CollectionManager;
import com.netexplode.jtunes.model.media.MediaCollection;
import com.netexplode.jtunes.model.media.SharedCollection;

/**
 * <code>DaapListener</code> represents .....
 * 
 * @author ykim
 * @version $Revision: 1.4 $
 * @since 0.1
 */
public class DaapListener implements ServiceListener {

	private static final Log log = LogFactory.getLog(DaapListener.class);

	private final static Hashtable<String, ItunesHost> servers = new Hashtable<String, ItunesHost>();

	private CollectionManager collectionManager;

	public void setCollectionManager(CollectionManager collectionManager) {
		this.collectionManager = collectionManager;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.jmdns.ServiceListener#serviceAdded(javax.jmdns.ServiceEvent)
	 */
	public void serviceAdded(ServiceEvent event) {
		log.info(event.getName());

		log.info("service added : " + event);
		JmDNS jmdns = event.getDNS();
		log.info(jmdns.getHostName());
		jmdns.requestServiceInfo(Constants.DAAP_SERVICE, event.getName());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.jmdns.ServiceListener#serviceRemoved(javax.jmdns.ServiceEvent)
	 */
	public void serviceRemoved(ServiceEvent event) {
		log.info(event.getName());
		try {
			servers.remove(event.getDNS().getInterface().getHostAddress());
		}
		catch (Exception e) {
			log.info(e, e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.jmdns.ServiceListener#serviceResolved(javax.jmdns.ServiceEvent)
	 */
	public void serviceResolved(ServiceEvent event) {

		log.info(event.getName());
		JmDNS jmdns = event.getDNS();
		log.info(jmdns.getHostName());
		log.info("create host");

		ItunesHost host = new ItunesHost(jmdns.getHostName(), event.getName(), ItunesHost.ITUNES_45);

		log.info("attempt connecting to " + host + ", " + host.getName() + "| version " + host.getVersion());

		ItunesConnection conn = null;

		try {
			conn = getItunesConnection(jmdns, event);
			if (null == conn) {
				log.info("null connection");
				return;
			}
			log.info("connecting");
			conn.connect();

			log.info("about to create collectoin");
			if (conn.isConnected()) {
				log.info("connection successful");
				Database[] dbs = conn.getDatabases();
				List<MediaCollection> list = new ArrayList<MediaCollection>();
				for (int i = 0; i < dbs.length; i++) {
					log.info("database = " + dbs[i].getName());
					final SharedCollection col = (SharedCollection) collectionManager.newSharedCollection();
					col.setId("" + dbs[i].getId());
					col.setName(dbs[i].getName());
					col.setDatabase(dbs[i]);
					col.setConnection(conn);
					col.setItunesHost(host);
					col.setTracks(conn.getTracklist(dbs[i].getId()));

					log.info("adding " + dbs[i].getName() + " with " + dbs[i].getTrackCount() + " | "
							+ conn.getTracklist(dbs[i].getId()).length);

					list.add(col);
				}

				collectionManager.setSharedCollections(list);

				servers.put(jmdns.getInterface().getHostAddress(), host);
				log.info("refreshing panel");
				jTunes.refreshSharedCollectionPanel();

				log.info("registerd " + host.getName());
			}
		}
		catch (Exception e) {
			log.info(e, e);
		}
		finally {
			if (conn != null && !conn.isConnected()) {
				conn = null;
			}
		}

	}

	private synchronized ItunesConnection getItunesConnection(JmDNS jmdns, ServiceEvent event) throws IOException,
			NoServerPermissionException {
		ItunesConnectionFactory factory = new ItunesConnectionFactory();
		ItunesConnection conn = null;
		final ServiceInfo info = event.getInfo();

		log.info("address: " + info.getHostAddress());
		log.info("port: " + info.getPort());
		log.info(info);

		if (info.getAddress().isAnyLocalAddress() || info.getAddress().isLoopbackAddress()) {
			log.info("local connection");
			// return null;
		}

		try {
			log.info("connecting");
			conn = factory.produceConnectionInstance(info.getHostAddress(), info.getPort(), event.getName());
		}
		catch (Exception e) {
			System.exit(1);
		}

		return conn;
	}
}